package com.acxy.ants.core.plugin.sqlmap;

import com.acxy.ants.common.kit.PathKit;
import com.acxy.ants.core.config.Modules;
import com.acxy.ants.core.Plugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.URLDecoder;
import java.util.Date;
import java.util.List;

/**
 * @author MrShun
 * @version 1.0
 * @Date 2017-05-20
 */
public class SqlMapPlugin implements Plugin {

    private static final Logger logger = LoggerFactory.getLogger(SqlMapPlugin.class);

    private String dirPath;

    //是否定时检查
    private boolean timerCheck = false;

    //子模块jar
    private String[] jars = null;

    private static DocumentBuilder documentBuilder;

    static {//调用jdk自己的xml解析，不想多加依赖。
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            documentBuilder = dbf.newDocumentBuilder();
        } catch (ParserConfigurationException ex) {
            throw new RuntimeException("I don`t know .", ex);
        }
    }

    /**
     * 通过构造赋值存放sql文件目录
     *
     * @param dirPath
     */
    public SqlMapPlugin(String dirPath) {
        init(dirPath, null, null);
    }

    public SqlMapPlugin(String dirPath, String[] jars) {
        init(dirPath, jars, null);
    }

    public SqlMapPlugin(String dirPath, Boolean timerCheck) {
        init(dirPath, null, timerCheck);
    }

    /**
     * 当timerCheck时定时检查资源文件防止重启，
     * true时用于调试，正式环境请消除
     * @param dirPath   xml文件路径
     * @param timerCheck 是否定时检查
     */
    private void init(String dirPath, String[] jars, Boolean timerCheck) {
        dirPath = dirPath.replace(".", "/");
        this.dirPath = PathKit.getClassPath() + dirPath;
        if(jars !=null && jars.length!=0) this.jars = jars;
        if(timerCheck != null) this.timerCheck = timerCheck;
    }

    public boolean start() {
        if(timerCheck){
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        while (true) {
                            Thread.sleep(2000);
                            logger.debug(new Date() + "thread timing begins to detect SqlMap resource files...");
                            parserSqlXml();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            new Thread(runnable).start();
        }else
            parserSqlXml();
        return true;
    }

    public void parserSqlXml(){
        SqlXmlParser.clear();
        //防止中文路径乱码
        try {
            dirPath = URLDecoder.decode(dirPath, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        if(jars != null && jars.length!=0) {
            for (String jar : jars) {
                logger.debug("开始初始化[{}]模块中的[XML SQL] 文件 ...", jar);
                List<InputStream> inputStreams = Modules.getModuleFileInputStream(jar, 0);
                for (InputStream inputStream : inputStreams) {
                    Document document = null;
                    try {
                        document = documentBuilder.parse(inputStream);
                    } catch (SAXException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    SqlXmlParser.parse(document);
                }
                logger.debug("{}模块中的[XML SQL] 初始化完成 ...", jar);
            }
        }
        logger.debug("初始化本身[XML SQL] 文件 ...");

        File dirFile = new File(dirPath);
        if (dirFile.isDirectory()) {
            File[] files = dirFile.listFiles(new FileFilter() {
                //过滤文件取xml文件
                public boolean accept(File pathname) {
                    return pathname.getName().endsWith(".xml");
                }
            });
            for (File file : files) {
                try {
                    //迭代解析sql xml

                    Document document = documentBuilder.parse(file);
                    SqlXmlParser.parse(document);
                    logger.debug("读取 {} 成功 ...", file.getPath());
                } catch (SAXException ex) {
                    new RuntimeException("the XML document format is incorrect!", ex);
                } catch (IOException ex) {
                    new RuntimeException("XML document read failed!", ex);
                }
            }
            logger.debug("本身[XML SQL] 初始化完成 ...");
        }
    }

    @Override
    public boolean destroy() {
        SqlXmlParser.clear();
        return true;
    }
}
